package com.zhiyou.app.shop.manager.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.sql.JoinType;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.zhiyou.app.shop.common.AycshopException;
import com.zhiyou.app.shop.common.ShopManageConstants;
import com.zhiyou.app.shop.common.util.Page;
import com.zhiyou.app.shop.common.util.ServiceUtil;
import com.zhiyou.app.shop.manager.dao.ICommentDao;
import com.zhiyou.app.shop.manager.dao.IFavGoodsDao;
import com.zhiyou.app.shop.manager.dao.IGoodsDao;
import com.zhiyou.app.shop.manager.dao.IShoppingTrolleyDao;
import com.zhiyou.app.shop.manager.dao.pojo.Comment;
import com.zhiyou.app.shop.manager.dao.pojo.FavGoods;
import com.zhiyou.app.shop.manager.dao.pojo.Goods;
import com.zhiyou.app.shop.manager.dao.pojo.GoodsCategory;
import com.zhiyou.app.shop.manager.dao.pojo.GoodsImg;
import com.zhiyou.app.shop.manager.dao.pojo.GoodsVisitLog;
import com.zhiyou.app.shop.manager.dao.pojo.Shop;
import com.zhiyou.app.shop.manager.dao.pojo.ShoppingTrolley;
import com.zhiyou.app.shop.manager.dao.pojo.UserDetail;
import com.zhiyou.app.shop.manager.service.IGoodsManageService;

@Service
public class GoodsManageServiceImpl implements IGoodsManageService {
	@Autowired
	private IGoodsDao goodsDao;
	@Autowired
	private IFavGoodsDao favGoodsDao;
	@Autowired
	private ICommentDao commentDao;
	@Autowired
	private IShoppingTrolleyDao shoppingTrolleyDao;
	
	public void saveOrUpdateGoods(Goods goods) {
		//validate from database
		DetachedCriteria dc = ServiceUtil.getADetachedCriteria(Goods.class);
		dc.add(Restrictions.eq("name", goods.getName()));
		dc.add(Restrictions.eq("shop.id", goods.getShop().getId()));
		dc.add(Restrictions.eq("isDelete", Boolean.FALSE));
		if(StringUtils.isNotBlank(goods.getId())){
			dc.add(Restrictions.ne("id", goods.getId()));
		}
		List list = goodsDao.findByCriteria(dc);
		if(null != list && list.size() > 0) throw new AycshopException("shopManage.goodsName.replicate");
		
		if(StringUtils.isBlank(goods.getId())){
			//fill goodsImg
			String firstImg = fillGoodsImgs(goods);
			goods.setCreateDate(new Date());
			goods.setOnSale(Boolean.FALSE);
			goods.setUserDetail(ServiceUtil.getCurrentUser());
			goods.setFirstImg(firstImg);
			goodsDao.save(goods);
		}else{
			Goods pojo = goodsDao.findById(goods.getId());
			String firstImg = fillGoodsImgs(goods,pojo);
			pojo.setName(goods.getName());
			pojo.setPrice(goods.getPrice());
			pojo.setGoodsCategory(goods.getGoodsCategory());
			pojo.setRemark(goods.getRemark());
			pojo.setSalesPromotionInfo(goods.getSalesPromotionInfo());
			pojo.setShareInfo(goods.getShareInfo());
			pojo.setFirstImg(firstImg);
			goodsDao.update(pojo);
		}

	}
	/**先执行要删除的，再实行要添加的**/
	private String fillGoodsImgs(Goods goods, Goods pojo) {
		Set<GoodsImg> goodsImgs = pojo.getGoodsImgs();
		String dbImgs = "", firstImg="";
		if(StringUtils.isNotBlank(goods.getGoodsImgPath())){
			String[] imgs = goods.getGoodsImgPath().split(",");
			firstImg = imgs[0];
			List<GoodsImg> toDelete = new ArrayList<GoodsImg>();
			for(GoodsImg gds : goodsImgs){//需要从db中删除的
				if(goods.getGoodsImgPath().indexOf(gds.getImgPath()) == -1){
					toDelete.add(gds);
				}else{
					dbImgs += gds.getImgPath()+",";
				}
			}
			//从db中删除
			for(GoodsImg deleteImg : toDelete){
				goodsImgs.remove(deleteImg);
			}
			for(String img : imgs){
				if(dbImgs.indexOf(img) == -1){//需要往db中添加的
					GoodsImg gi = new GoodsImg(pojo, img, new Date(), ShopManageConstants.IMGSPERGOODS);
					goodsImgs.add(gi);
				}
			}
		}else{
			goodsImgs.clear();
		}
		return firstImg;
	}

	/**由于使用了hibernate的inverse="true"属性，img表的控制交由主表来维护，<br>
	 * 所以直接在goods中添加goodsImg就可以保存到子表中*/
	private String fillGoodsImgs(Goods goods) {
		String firstImg = "";
		if(StringUtils.isNotBlank(goods.getGoodsImgPath())){
			String[] imgs = goods.getGoodsImgPath().split(",");
			firstImg = imgs[0]; 
			int i=0;
			for(String path : imgs){
				GoodsImg gi = new GoodsImg(goods, path, new Date(), i++);
				goods.getGoodsImgs().add(gi);
			}
		}
		return firstImg;
	}


	public void queryGoodsWithPage(Page page, Goods goods, Order order) {
		DetachedCriteria dc = DetachedCriteria.forClass(Goods.class);
		if(null != goods.getShop() && null != goods.getShop().getId()){
			dc.add(Restrictions.eq("shop.id", goods.getShop().getId()));
		}
		if(null != goods.getGoodsCategory()){
			dc.add(Restrictions.eq("goodsCategory.id", goods.getGoodsCategory().getId()));
		}
		if(StringUtils.isNotBlank(goods.getName())){
			dc.add(Restrictions.like("name", goods.getName(), MatchMode.ANYWHERE));
		}
		dc.createAlias("goodsCategory", "gc");
		
		if(StringUtils.isNotBlank(goods.getId())){
			dc.add(Restrictions.eq("id", goods.getId()));
		}
		if(goods.isQueryShopInfo()){
			dc.createAlias("shop", "sp");
			if(null != goods.getShop() && null != goods.getShop().getName()){
				dc.add(Restrictions.like("sp.name", goods.getShop().getName(), MatchMode.ANYWHERE));
			}
		}
		
		dc.add(Restrictions.eq("isDelete", Boolean.FALSE));
		goodsDao.findByCriteria(page, dc, order);
		if(null != page.getResult()){
			List<Object[]> list = page.getResult(); 
			List<Goods> goodsList = new ArrayList<Goods>(list.size());
			int index = goods.isQueryShopInfo() ? 2 : 1;
			for(Object[] array : list){
				Goods dg = (Goods)array[index];
				goodsList.add(dg);
			}
			page.setResult(goodsList);
		}
	}

	public void deleteGoods(String ids) {
		goodsDao.logicBatchDeleteByIds(ids);
	}

	
	public void setSaleState(String ids, boolean onSale) {
		goodsDao.setSaleState(ids, onSale);
		
	}
	
	public Goods findGoodsById(String id) {
		Goods goods = goodsDao.findById(id);
		return goods;
	}

	public Goods findGoodsWithShopUserAndImgs(String id){
		Goods goods = goodsDao.findById(id);
		goods.getShop().getUserDetail();
		goods.getGoodsImgs().iterator();
		return goods;
	}
	public List<GoodsImg> findGoodsImgByGoodsId(String goodsId) {
		return goodsDao.findGoodsImgByGoodsId(goodsId,null);
	}
	
	
	public void addMyFavGoods(UserDetail ud, Goods goods) {
		DetachedCriteria dc = DetachedCriteria.forClass(FavGoods.class);
		dc.add(Restrictions.eq("goods.id", goods.getId()));
		dc.add(Restrictions.eq("userDetail.id", ud.getId()));
		List<FavGoods> list = favGoodsDao.findByCriteria(dc, null);
		if(null == list || list.size() < 1){
			FavGoods favGoods = new FavGoods();
			favGoods.setUserDetail(ud);
			favGoods.setGoods(goods);
			favGoods.setCreateDate(new Date());
			favGoodsDao.save(favGoods);
		}
	}
	
	
	public void findMyFavGoodsByPage(Page page, UserDetail ud, Order order) {
		DetachedCriteria dc = DetachedCriteria.forClass(FavGoods.class, "fav");
		dc.createAlias("fav.goods", "g");
//		dc.add(Restrictions.eqProperty("g.id", "fav.goods.id"));
		dc.add(Restrictions.eq("fav.userDetail.id", ud.getId()));
		dc.add(Restrictions.eq("g.isDelete", Boolean.FALSE));
		favGoodsDao.findByCriteria(page, dc, order);
		List<Object[]> list = page.getResult();
		List<Goods> listGoods = new ArrayList<Goods>(list.size());
		page.setResult(listGoods);
		if(null != list && list.size()>0){
			for(Object[] objs : list){
				Goods gd = (Goods)objs[0];
				listGoods.add(gd);
			}
		}
	}
	
	public void saveGoodsVisitLog(Goods goods, UserDetail ud) {
		GoodsVisitLog log = new GoodsVisitLog(ud, goods , new Date());
		goodsDao.saveGoodsVisitLog(log);
	}
	
	public void saveGoodsComment(Comment comment){
		//查询该用户对该商品是否已评论过
		DetachedCriteria dc = DetachedCriteria.forClass(Comment.class);
		dc.add(Restrictions.eq("goods.id", comment.getGoods().getId()));
		dc.add(Restrictions.eq("commentUser.id", comment.getCommentUser().getId()));
		List list = commentDao.findByCriteria(dc, null);
		if(null != list && list.size() > 0) 
			throw new AycshopException("shopManage.goodsComment.repeat");
		comment.setCommentDate(new Date());
		commentDao.save(comment);
	}
	
	public void findCommentsByGoods(Page page, Goods goods){
		DetachedCriteria dc = DetachedCriteria.forClass(Comment.class);
		dc.createAlias("commentUser", "u");
		dc.add(Restrictions.eq("goods.id", goods.getId()));
		commentDao.findByCriteria(page, dc, Order.desc("commentDate"));
		List<Object[]> objs = page.getResult();
		if(null != objs){
			List<Comment> list = new ArrayList<Comment>(objs.size());
			page.setResult(list);
			for(Object[] array : objs){
				list.add((Comment)array[1]);
			}
		}
	}
	
	public void saveShoppingTrolley(ShoppingTrolley trolley) {
		//判断购物车中是否已经有这个商品了
		List list = shoppingTrolleyDao.findByCriteria(trolley);
		if(null == list || list.size()==0){
			shoppingTrolleyDao.save(trolley);
		}else{
			ShoppingTrolley pojo = (ShoppingTrolley)list.get(0);
			pojo.setAmount(pojo.getAmount()+trolley.getAmount());
			shoppingTrolleyDao.update(pojo);
		}
	}
	
	public void deleteShoppingTrolley(String trolleyId) {
		ShoppingTrolley t = shoppingTrolleyDao.findById(trolleyId);
		shoppingTrolleyDao.delete(t);
	}
	
	public void updateShoppingTrolley(String trolleyId, int amount) {
		ShoppingTrolley t = shoppingTrolleyDao.findById(trolleyId);
		t.setAmount(amount);
		shoppingTrolleyDao.update(t);
	}
	
	public List<ShoppingTrolley> findShoppingTrolleyByUser(UserDetail ud) {
		return shoppingTrolleyDao.findTrolleyDetailByUserId(ud.getId());
	}
	
	public Goods findGoodsWithAssociate(String goodsId) {
		Goods goods = goodsDao.findById(goodsId);
		goods.getGoodsCategory().getName();
		goods.getGoodsImgs().iterator();
		return goods;
	}
	
	public void deleteGoodsComments(String commentId) {
		Comment comment = commentDao.findById(commentId);
		commentDao.delete(comment);
		
	}
	
	
}
